package com.cgs.mongo.extractor;

import com.cgs.mongo.exception.ParserException;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoIterable;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import org.bson.BsonString;
import org.bson.Document;

import java.util.Optional;

/**
 * 提取器抽象层
 * 判断了类型，区分不同的方法执行
 *
 * @param <T>
 */
public abstract class AbstractCursorExtractor<T> implements CursorExtractor<Optional<T>> {

    @Override
    public Optional<T> extractData(Object result) {
        return Optional.ofNullable(result).map(this::mapper);
    }

    private T mapper(Object result) {
        if (result instanceof MongoIterable) {
            MongoCursor<Object> iterator = ((MongoIterable) result).iterator();
            return mapIterable(iterator);
        } else if (result instanceof Document) {
            return mapDocument((Document) result);
        } else if (result instanceof BsonString) {
            return mapBsonString((BsonString) result);
        } else if (result instanceof Long) {
            return mapLong((Long) result);
        } else if (result instanceof UpdateResult) {
            return mapUpdateResult((UpdateResult) result);
        } else if (result instanceof DeleteResult) {
            return mapDeleteResult((DeleteResult) result);
        } else {
            return mapOther(result);
        }
    }

    /**
     * 从迭代器中提取数据
     *
     * @param iterator 迭代器
     * @return 泛型对象
     * @see #forEach(MongoCursor, RowMapper)
     */
    protected abstract T mapIterable(MongoCursor<Object> iterator);

    /**
     * 处理long类型数据
     *
     * @param result 数据
     * @return 泛型对象
     */
    protected abstract T mapLong(Long result);

    /**
     * 处理UpdateResult类型数据
     *
     * @param result 数据
     * @return 泛型对象
     */
    protected abstract T mapUpdateResult(UpdateResult result);

    /**
     * 处理DeleteResult类型数据
     *
     * @param result 数据
     * @return 泛型对象
     */
    protected abstract T mapDeleteResult(DeleteResult result);

    /**
     * 处理BsonString类型数据
     *
     * @param result 数据
     * @return 泛型对象
     */
    protected abstract T mapBsonString(BsonString result);

    /**
     * 处理Document类型数据
     *
     * @param result 数据
     * @return 泛型对象
     */
    protected abstract T mapDocument(Document result);

    /**
     * 其他类型数据的转换
     *
     * @param result 数据
     * @return 泛型对象
     */
    protected T mapOther(Object result) {
        throw ParserException.instance("无法解析的结果类型：");
    }
}
